package com.anxin.act.task.service;

import com.anxin.act.process.service.FlowInterfacesService;
import com.anxin.act.task.complete.TaskComplete;
import com.anxin.act.task.dao.WfActHiTaskDao;
import com.anxin.act.task.dao.WfActRuTaskDao;
import com.anxin.act.task.dto.AdjustNodeDTO;
import com.anxin.act.task.entity.ViewRuTask;
import com.anxin.act.task.vo.ActivityVO;
import com.anxin.act.task.vo.ChannelVo;
import com.anxin.act.task.vo.TaskVo;
import com.anxin.act.utils.ActSqlUtils;
import com.anxin.act.utils.ActTaskUtils;
import com.anxin.act.utils.ActUtils;
import com.anxin.common.constant.HttpStatus;
import com.anxin.common.utils.StringUtils;
import com.anxin.common.utils.sys.UserUtils;
import com.anxin.framework.redis.MqProducer;
import com.anxin.framework.web.entity.AjaxResult;
import com.anxin.framework.web.page.PageDomain;
import com.anxin.framework.web.page.TableDataInfo;
import com.anxin.framework.web.page.TableSupport;
import com.anxin.sys.system.entity.SysUser;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.task.NativeTaskQuery;
import org.activiti.engine.task.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.support.TaskUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author: liuxiangyu
 * @date: 2020/5/18 14:27
 */
@Service
public class ActChannelService {

    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private JumpTaskService jumpTaskService;
    @Autowired
    private ViewRuTaskService viewRuTaskService;
    @Autowired
    private WfActRuTaskDao wfActRuTaskDao;
    @Autowired
    private WfActHiTaskDao wfActHiTaskDao;
    @Autowired
    private ActDockingService actDockingService;
    @Autowired
    private MqProducer mqProducer;
    @Autowired
    private FlowInterfacesService flowInterfacesService;

    public List<ViewRuTask> list(TaskVo taskVo){

        ViewRuTask viewRuTask = new ViewRuTask();

        viewRuTask.setTitle(taskVo.getTitle());
        viewRuTask.setProcessName(taskVo.getProcessName());

        // String userName = "-1";
        if (StringUtils.isNotBlank(taskVo.getAssignee())){
            String userName = UserUtils.getUser(taskVo.getAssignee()).getUserName();
            viewRuTask.setAssignee(userName);
        }

        viewRuTask.setHang("N");
        return viewRuTaskService.findPage(viewRuTask);

    }

    /**
     * 推送待办
     * @param viewRuTask 待办任务对象
     * @param targetUser 新的审批人
     */
    public void sendTodoTask(ViewRuTask viewRuTask,SysUser targetUser){
        // 删除源用户的待办
        actDockingService.delTaskByUserName(viewRuTask.getId(),viewRuTask.getAssignee());
        // 给新用户推送待办
        actDockingService.sendTask(viewRuTask,targetUser.getId());

    }


    /**
     * 流程疏导
     * @param channelVo
     */
    public void channelTask(ChannelVo channelVo){
        String target = channelVo.getTargetUser();
        SysUser targetUser = UserUtils.getUser(target);
        for (int i = 0; i < channelVo.getTasks().size(); i++) {
            String taskId = channelVo.getTasks().getString(i);
            ViewRuTask viewRuTask = viewRuTaskService.get(taskId);
            if ("actTask".equals(viewRuTask.getType())){
                taskService.setAssignee(taskId, targetUser.getUserName());
            }else {
                wfActRuTaskDao.updateAssignee(taskId,targetUser.getUserName());
                wfActHiTaskDao.updateAssignee(taskId,targetUser.getUserName());
            }

            // 推送待办
            this.sendTodoTask(viewRuTask,targetUser);
            // 调用改派任务接口
            flowInterfacesService.reassign(viewRuTask,targetUser);
        }


    }

    /**
     * 查询流程全部节点
     * @param taskId
     * @return
     */
    public List<ActivityVO> getActivityList(String taskId){
        List<ActivityVO> resList = new ArrayList<>();

        Task task = ActTaskUtils.getTask(taskId);
        ProcessDefinitionEntity pde = (ProcessDefinitionEntity) ((RepositoryServiceImpl)repositoryService).getDeployedProcessDefinition(task.getProcessDefinitionId());

        List<ActivityImpl> activityList = pde.getActivities();
        Map<String,ActivityVO> activityMap = new HashMap<>();

        // 流程启动节点
        ActivityImpl startEvent = null;

        for (ActivityImpl activity : activityList) {
            Object type = activity.getProperties().get("type");
            if ("userTask".equals(type)){
                activityMap.put(activity.getId(),new ActivityVO(activity.getId(),activity.getProperties().get("name").toString()));
//                resList.add(new ActivityVO(activity.getId(),activity.getProperties().get("name").toString()));
            }else if ("startEvent".equals(type)){
                startEvent = activity;
            }
        }

        // 需要过滤的节点ID
        List<String> filtrationNodeIdList = new ArrayList<>();

        this.fileActivityImpl(startEvent,activityMap,resList,filtrationNodeIdList);

//        for (ActivityImpl activity : activities) {
//            Object type = activity.getProperties().get("type");
//            if ("userTask".equals(type)){
//                resList.add(new ActivityVO(activity.getId(),activity.getProperties().get("name").toString()));
//            }
//        }

        return resList;
    }

    /**
     * 递归查找节点
     *
     * @param sourceEvent
     * @param activityMap
     * @param resList
     */
    private void fileActivityImpl(PvmActivity sourceEvent, Map<String, ActivityVO> activityMap, List<ActivityVO> resList,List<String> filtrationNodeIdList) {
        List<PvmTransition> outgoingTransitions = sourceEvent.getOutgoingTransitions();
        for (PvmTransition pvmTransition : outgoingTransitions) {
            ActivityVO activityVO = activityMap.get(pvmTransition.getDestination().getId());
            if (activityVO != null){
                resList.add(activityVO);
                activityMap.remove(pvmTransition.getDestination().getId());
            }
        }

        for (PvmTransition outgoingTransition : outgoingTransitions) {
            PvmActivity destination = outgoingTransition.getDestination();
            if (destination != null && !filtrationNodeIdList.contains(destination.getId())){
                filtrationNodeIdList.add(destination.getId());
                this.fileActivityImpl(destination,activityMap,resList,filtrationNodeIdList);
            }
        }

    }


    /**
     * 检查任务是否可以调整节点
     * @param adjustNodeDTO
     * @return
     */
    public AjaxResult submitAdjustNodeCheck(AdjustNodeDTO adjustNodeDTO){

        ViewRuTask viewRuTask = viewRuTaskService.get(adjustNodeDTO.getTaskId());
        if (!"actTask".equals(viewRuTask.getType())){
            return AjaxResult.setSuccessData("加签节点,无法调整");
        }


        return AjaxResult.success();
    }


    /**
     * 调整节点
     * @param adjustNodeDTO
     * @return
     */
    public void submitAdjustNode(AdjustNodeDTO adjustNodeDTO){
        Task task = ActTaskUtils.getTask(adjustNodeDTO.getTaskId());
        SysUser user = UserUtils.getUser();
        ActivityImpl activityImpl = ActUtils.getActivityImpl(task.getProcessDefinitionId(), adjustNodeDTO.getActivityId());
        String comment = user.getNickName() +"将任务调整至"+activityImpl.getProperties().get("name");

        //taskService.deleteComments(task.getId(), task.getProcessInstanceId());
        taskService.addComment(task.getId(), task.getProcessInstanceId(), comment);

        Map<String,Object> taskVar = new HashMap<>();

        taskService.setVariableLocal(task.getId(),"act_adjustNode",true);
        taskService.setVariableLocal(task.getId(),"act_adjustNode_user",user.getNickName());
        taskService.setVariableLocal(task.getId(),"act_adjustNode_node",activityImpl.getProperties().get("name"));

        // 驳回节点
        jumpTaskService.jumpTask(task.getProcessInstanceId(), task.getId(),adjustNodeDTO.getActivityId(), taskVar);
        // 签收任务
        ActTaskUtils.claimTask(task.getProcessInstanceId());

        // 如果是会签节点则将其他任务也一并提交
        List<Task> taskList = ActTaskUtils.getTaskList(task.getTaskDefinitionKey(), task.getProcessInstanceId());
        for (Task countersignTask : taskList) {
            //taskService.deleteComments(task.getId(), task.getProcessInstanceId());
            taskService.addComment(countersignTask.getId(), countersignTask.getProcessInstanceId(), comment);
            taskService.complete(countersignTask.getId(),taskVar);
        }

        // 对接待办推送
        mqProducer.sendMessage(ActDockingService.class,task.getProcessInstanceId());
    }
}
